﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.ComponentModel;

namespace Visualization.DataModel
{
    /// <summary>
    /// The DataProcessor Class provides a client program the ability to reformat CSV data into a processed and ordered
    /// XML file asynchronously
    /// </summary>
    public class DataProcessor
    {
        Dictionary<int, SFPStep> steps = new Dictionary<int, SFPStep>();
        public BackgroundWorker worker = new BackgroundWorker();

        /// <summary>
        /// DataProcessor Constructor
        /// </summary>
        public DataProcessor()
        {
            worker.WorkerReportsProgress = true;
        }

        /// <summary>
        /// Asynchronously reads specified CSV file and creates SFP Steps.
        /// </summary>
        /// <param name="fileName">Input CSV file</param>
        public void retrieveCSVData(string fileName)
        {
            worker.ReportProgress(0, "Reading CSV File...");
            ParticleReader pReader = new ParticleReader();
            pReader.readCSV(fileName);
            steps = pReader.SFPSteps;
            worker.ReportProgress(100, "Done!");
        }

        /// <summary>
        /// Asynchronously process particles for probability
        /// </summary>
        public void processParticles()
        {
            worker.ReportProgress(0, "Processing SFP Steps...");
            foreach (int key in steps.Keys)
            {
                SFPStep step = steps[key];
                worker.ReportProgress((int)(((double)key / (double)steps.Count) * 100), "Processing SFP Step " + step.Step);
                step.calcStandardDeviation();
                step.generateProbabilities();
            }
            worker.ReportProgress(100, "Processed SFP Steps");
        }

        /// <summary>
        /// Asynchronously write out processed SFP steps into XML format.
        /// </summary>
        /// <param name="fileName">Output XML file</param>
        public void writeProcessedData(string fileName){
            worker.ReportProgress(0, "Writing XML File");
            XmlTextWriter writer = new XmlTextWriter(fileName, Encoding.Default);
            writer.Formatting = Formatting.Indented;
            writer.WriteStartDocument();
            writer.WriteStartElement("SFPSteps");
            List<SFPStep> sfpSteps = steps.Values.ToList<SFPStep>();
            foreach (SFPStep step in steps.Values){
                worker.ReportProgress((int)(((double)sfpSteps.IndexOf(step) / (double)sfpSteps.Count) * 100), "Writing SFP Step " + step.Step);
                writer.WriteStartElement("Step");
                writer.WriteAttributeString("Step", step.Step.ToString());
                writer.WriteAttributeString("X", step.X.ToString());
                writer.WriteAttributeString("Y", step.Y.ToString());
                writer.WriteAttributeString("Theta", step.Theta.ToString());
                writer.WriteAttributeString("RefTime", step.RefTime.ToString());
                writer.WriteAttributeString("HX", step.HighestProbabilityParticle.X.ToString());
                writer.WriteAttributeString("HY", step.HighestProbabilityParticle.Y.ToString());
                writer.WriteAttributeString("HT", step.HighestProbabilityParticle.Theta.ToString());
                writer.WriteAttributeString("HP", step.HighestProbabilityParticle.Probability.ToString());
                writer.WriteAttributeString("XBar", step.xBar.ToString());
                writer.WriteAttributeString("XSigma", step.xSigma.ToString());
                writer.WriteAttributeString("YBar", step.yBar.ToString());
                writer.WriteAttributeString("YSigma", step.ySigma.ToString());
                writer.WriteAttributeString("ThetaBar", step.thetaBar.ToString());
                writer.WriteAttributeString("ThetaSigma", step.thetaSigma.ToString());
                writer.WriteStartElement("Particles");
                foreach (Particle p in step.particles){
                    writer.WriteStartElement("Particle");
                    writer.WriteAttributeString("X", p.X.ToString());
                    writer.WriteAttributeString("Y", p.Y.ToString());
                    writer.WriteAttributeString("Theta", p.Theta.ToString());
                    writer.WriteAttributeString("Probability", p.Probability.ToString());
                    writer.WriteEndElement();
                }
                writer.WriteEndElement();
                writer.WriteEndElement();
            }
            writer.WriteEndElement();
            writer.WriteEndDocument();
            writer.Close();
            worker.ReportProgress(100, "Done");
        }
    }
}
